package com.hospital.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.entity.Department;
import com.hospital.entity.MedicalRecord;
import com.hospital.entity.User;
import com.hospital.entity.Ward;
import com.hospital.mapper.MedicalRecordMapper;
import com.hospital.service.DepartmentService;
import com.hospital.service.MedicalRecordService;
import com.hospital.service.UserService;
import com.hospital.service.WardService;
import com.hospital.util.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * 就诊记录服务实现类
 *
 * @author Hospital Management System
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MedicalRecordServiceImpl extends ServiceImpl<MedicalRecordMapper, MedicalRecord> implements MedicalRecordService {

    private final UserService userService;
    private final DepartmentService departmentService;
    private final WardService wardService;
    private final Lock recordNoLock = new ReentrantLock();
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

    @Override
    public boolean save(MedicalRecord medicalRecord) {
        // 生成并设置病历编号
        String recordNo = generateRecordNo();
        medicalRecord.setRecordNo(recordNo);
        return super.save(medicalRecord);
    }

    /**
     * 生成病历编号
     * 格式：MR + 年月日 + 4位序号
     * 示例：MR202403150001
     */
    private String generateRecordNo() {
        recordNoLock.lock();
        try {
            String today = LocalDateTime.now().format(DATE_FORMATTER);
            String prefix = "MR" + today;
            
            // 查询当天最大序号
            QueryWrapper<MedicalRecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.likeRight("record_no", prefix)
                       .orderByDesc("record_no")
                       .last("LIMIT 1");
            
            MedicalRecord lastRecord = getOne(queryWrapper);
            
            int sequence = 1;
            if (lastRecord != null && lastRecord.getRecordNo() != null) {
                // 提取序号并加1
                String lastSequence = lastRecord.getRecordNo().substring(10); // 获取最后4位
                sequence = Integer.parseInt(lastSequence) + 1;
            }
            
            // 格式化4位序号
            return String.format("%s%04d", prefix, sequence);
        } finally {
            recordNoLock.unlock();
        }
    }

    @Override
    public List<MedicalRecord> getUserMedicalRecords(Long userId) {
        QueryWrapper<MedicalRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                   .eq("deleted", 0);
        log.info("查询用户就诊记录，用户ID: {}", userId);
        return list(queryWrapper);
    }

    @Override
    public List<MedicalRecord> getDoctorMedicalRecords(String patientName) {
        Long currentDoctorId = UserContext.getCurrentUser().getId();
        QueryWrapper<MedicalRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("doctor_id", currentDoctorId)
                   .eq("deleted", 0);
        
        // 如果需要根据患者姓名搜索，需要连表查询，这里简化处理
        if (StringUtils.hasText(patientName)) {
            // 实际项目中应该join user表或者先查用户ID再查就诊记录
            log.info("按患者姓名搜索功能待完善: {}", patientName);
        }
        
        return list(queryWrapper);
    }

    @Override
    public List<MedicalRecord> getMedicalRecords(String keyword) {
        QueryWrapper<MedicalRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);
        
        // 如果需要根据关键词搜索用户名或医生名，需要连表查询，这里简化处理
        if (StringUtils.hasText(keyword)) {
            log.info("按关键词搜索功能待完善: {}", keyword);
        }
        
        return list(queryWrapper);
    }

    @Override
    public Map<String, Object> getDoctorMedicalRecordsWithPagination(Long doctorId, String patientName, 
                                                                     Integer status, Integer page, Integer size) {
        // 创建分页对象
        Page<MedicalRecord> pageObj = new Page<>(page, size);
        
        // 构建查询条件
        QueryWrapper<MedicalRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("doctor_id", doctorId)
               .eq("deleted", 0);
        
        // 如果提供了患者姓名，先查询用户ID
        if (StringUtils.hasText(patientName)) {
            QueryWrapper<User> userWrapper = new QueryWrapper<>();
            userWrapper.like("name", patientName)
                      .eq("role", 1)  // 1-患者
                      .eq("deleted", 0);
            List<User> users = userService.list(userWrapper);
            if (!users.isEmpty()) {
                List<Long> userIds = users.stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
                wrapper.in("user_id", userIds);
            } else {
                // 如果没有找到匹配的患者，返回空结果
                return getEmptyResult(page, size);
            }
        }
        
        // 状态筛选
        if (status != null) {
            wrapper.eq("status", status);
        }
        
        // 按创建时间降序排列
        wrapper.orderByDesc("create_time");
        
        // 执行分页查询
        IPage<MedicalRecord> pageResult = page(pageObj, wrapper);
        
        // 获取查询结果
        List<MedicalRecord> records = pageResult.getRecords();
        
        // 填充关联信息
        fillRelatedInfo(records);
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("list", records);
        result.put("total", pageResult.getTotal());
        result.put("page", pageResult.getCurrent());
        result.put("size", pageResult.getSize());
        result.put("pages", pageResult.getPages());
        
        return result;
    }

    @Override
    public Map<String, Object> getMedicalRecordsWithPagination(String patientName, String doctorName, 
                                                               Integer status, Integer page, Integer size) {
        // 创建分页对象
        Page<MedicalRecord> pageObj = new Page<>(page, size);
        
        // 构建查询条件
        QueryWrapper<MedicalRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", 0);
        
        // 如果提供了患者姓名，先查询用户ID
        if (StringUtils.hasText(patientName)) {
            QueryWrapper<User> userWrapper = new QueryWrapper<>();
            userWrapper.like("name", patientName)
                      .eq("role", 1)  // 1-患者
                      .eq("deleted", 0);
            List<User> users = userService.list(userWrapper);
            if (!users.isEmpty()) {
                List<Long> userIds = users.stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
                wrapper.in("user_id", userIds);
            } else {
                // 如果没有找到匹配的患者，返回空结果
                return getEmptyResult(page, size);
            }
        }
        
        // 如果提供了医生姓名，先查询医生ID
        if (StringUtils.hasText(doctorName)) {
            QueryWrapper<User> doctorWrapper = new QueryWrapper<>();
            doctorWrapper.like("name", doctorName)
                        .eq("role", 2)  // 2-医生
                        .eq("deleted", 0);
            List<User> doctors = userService.list(doctorWrapper);
            if (!doctors.isEmpty()) {
                List<Long> doctorIds = doctors.stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
                wrapper.in("doctor_id", doctorIds);
            } else {
                // 如果没有找到匹配的医生，返回空结果
                return getEmptyResult(page, size);
            }
        }
        
        // 状态筛选
        if (status != null) {
            wrapper.eq("status", status);
        }
        
        // 按创建时间降序排列
        wrapper.orderByDesc("create_time");
        
        // 执行分页查询
        IPage<MedicalRecord> pageResult = page(pageObj, wrapper);
        
        // 获取查询结果
        List<MedicalRecord> records = pageResult.getRecords();
        
        // 填充关联信息
        fillRelatedInfo(records);
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("list", records);
        result.put("total", pageResult.getTotal());
        result.put("page", pageResult.getCurrent());
        result.put("size", pageResult.getSize());
        result.put("pages", pageResult.getPages());
        
        return result;
    }

    /**
     * 获取空结果
     */
    private Map<String, Object> getEmptyResult(Integer page, Integer size) {
        Map<String, Object> result = new HashMap<>();
        result.put("list", Collections.emptyList());
        result.put("total", 0);
        result.put("page", page);
        result.put("size", size);
        result.put("pages", 0);
        return result;
    }

    @Override
    public void fillRelatedInfo(MedicalRecord record) {
        if (record == null) {
            return;
        }
        
        // 填充患者信息
        if (record.getUserId() != null) {
            User user = userService.getById(record.getUserId());
            if (user != null) {
                record.setUserName(user.getName());
            }
        }
        
        // 填充医生信息
        if (record.getDoctorId() != null) {
            User doctor = userService.getById(record.getDoctorId());
            if (doctor != null) {
                record.setDoctorName(doctor.getName());
            }
        }
        
        // 填充科室信息
        if (record.getDepartmentId() != null) {
            Department department = departmentService.getById(record.getDepartmentId());
            if (department != null) {
                record.setDepartmentName(department.getName());
            }
        }

        // 填充病房信息
        if (record.getWardId() != null) {
            Ward ward = wardService.getById(record.getWardId());
            if (ward != null) {
                record.setWardName(ward.getName());
            }
        }
    }

    @Override
    public void fillRelatedInfo(List<MedicalRecord> records) {
        if (records == null || records.isEmpty()) {
            return;
        }

        // 获取所有用户ID、医生ID和科室ID
        List<Long> userIds = records.stream()
                .map(MedicalRecord::getUserId)
                .filter(id -> id != null)
                .distinct()
                .collect(Collectors.toList());

        List<Long> doctorIds = records.stream()
                .map(MedicalRecord::getDoctorId)
                .filter(id -> id != null)
                .distinct()
                .collect(Collectors.toList());

        List<Long> departmentIds = records.stream()
                .map(MedicalRecord::getDepartmentId)
                .filter(id -> id != null)
                .distinct()
                .collect(Collectors.toList());

        List<Long> wardIds = records.stream()
                .map(MedicalRecord::getWardId)
                .filter(id -> id != null)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询用户信息
        Map<Long, User> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<User> users = userService.listByIds(userIds);
            userMap = users.stream()
                    .collect(Collectors.toMap(User::getId, user -> user));
        }

        // 批量查询医生信息
        Map<Long, User> doctorMap = new HashMap<>();
        if (!doctorIds.isEmpty()) {
            List<User> doctors = userService.listByIds(doctorIds);
            doctorMap = doctors.stream()
                    .collect(Collectors.toMap(User::getId, doctor -> doctor));
        }

        // 批量查询科室信息
        Map<Long, Department> departmentMap = new HashMap<>();
        if (!departmentIds.isEmpty()) {
            List<Department> departments = departmentService.listByIds(departmentIds);
            departmentMap = departments.stream()
                    .collect(Collectors.toMap(Department::getId, dept -> dept));
        }

        // 批量查询病房信息
        Map<Long, Ward> wardMap = new HashMap<>();
        if (!wardIds.isEmpty()) {
            List<Ward> wards = wardService.listByIds(wardIds);
            wardMap = wards.stream()
                    .collect(Collectors.toMap(Ward::getId, ward -> ward));
        }

        // 填充关联信息
        final Map<Long, User> finalUserMap = userMap;
        final Map<Long, User> finalDoctorMap = doctorMap;
        final Map<Long, Department> finalDepartmentMap = departmentMap;
        final Map<Long, Ward> finalWardMap = wardMap;
        
        records.forEach(record -> {
            // 填充患者姓名
            if (record.getUserId() != null && finalUserMap.containsKey(record.getUserId())) {
                User user = finalUserMap.get(record.getUserId());
                record.setUserName(user.getName());
            }

            // 填充医生姓名
            if (record.getDoctorId() != null && finalDoctorMap.containsKey(record.getDoctorId())) {
                User doctor = finalDoctorMap.get(record.getDoctorId());
                record.setDoctorName(doctor.getName());
            }

            // 填充科室名称
            if (record.getDepartmentId() != null && finalDepartmentMap.containsKey(record.getDepartmentId())) {
                Department department = finalDepartmentMap.get(record.getDepartmentId());
                record.setDepartmentName(department.getName());
            }

            // 填充病房信息
            if (record.getWardId() != null && finalWardMap.containsKey(record.getWardId())) {
                Ward ward = finalWardMap.get(record.getWardId());
                record.setWardName(ward.getName());
            }
        });
    }

    @Override
    public boolean assignBed(Long recordId, Long wardId, Integer bedNumber, Integer estimatedDays) {
        MedicalRecord record = getById(recordId);
        if (record == null) {
            throw new RuntimeException("就诊记录不存在");
        }

        // 检查病房是否存在且可用
        Ward ward = wardService.getById(wardId);
        if (ward == null) {
            throw new RuntimeException("病房不存在");
        }
        if (ward.getStatus() != 1) {
            throw new RuntimeException("病房不可用");
        }

        // 检查床位是否已被占用
        if (ward.getOccupiedBeds() >= ward.getTotalBeds()) {
            throw new RuntimeException("病房已满");
        }

        // 检查指定的床位号是否有效
        if (bedNumber <= 0 || bedNumber > ward.getTotalBeds()) {
            throw new RuntimeException("无效的床位号");
        }

        // 检查床位是否已被占用
        QueryWrapper<MedicalRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ward_id", wardId)
                   .eq("bed_number", bedNumber)
                   .eq("hospitalization_status", 1) // 已入院状态
                   .eq("deleted", 0);
        if (count(queryWrapper) > 0) {
            throw new RuntimeException("该床位已被占用");
        }

        // 更新就诊记录
        record.setNeedHospitalization(true);
        record.setWardId(wardId);
        record.setBedNumber(bedNumber);
        record.setEstimatedDays(estimatedDays);
        record.setHospitalizationStatus(0); // 设置为未住院状态
        record.setEstimatedDischargeTime(LocalDateTime.now().plusDays(estimatedDays));
        
        boolean success = updateById(record);
        if (success) {
            // 更新病房床位占用情况
            wardService.updateBedOccupancy(wardId, ward.getOccupiedBeds() + 1);
        }
        
        return success;
    }

    @Override
    public boolean admission(Long recordId) {
        MedicalRecord record = getById(recordId);
        if (record == null) {
            throw new RuntimeException("就诊记录不存在");
        }

        if (!Boolean.TRUE.equals(record.getNeedHospitalization())) {
            throw new RuntimeException("该患者无需住院");
        }

        if (record.getHospitalizationStatus() != 0) {
            throw new RuntimeException("患者已入院或已出院");
        }

        // 更新就诊记录
        record.setHospitalizationStatus(1); // 设置为已入院状态
        record.setAdmissionTime(LocalDateTime.now());
        
        return updateById(record);
    }

    @Override
    public boolean discharge(Long recordId) {
        MedicalRecord record = getById(recordId);
        if (record == null) {
            throw new RuntimeException("就诊记录不存在");
        }

        if (record.getHospitalizationStatus() != 1) {
            throw new RuntimeException("患者未入院或已出院");
        }

        // 更新就诊记录
        record.setHospitalizationStatus(2); // 设置为已出院状态
        record.setActualDischargeTime(LocalDateTime.now());
        
        boolean success = updateById(record);
        if (success && record.getWardId() != null) {
            // 更新病房床位占用情况
            Ward ward = wardService.getById(record.getWardId());
            if (ward != null && ward.getOccupiedBeds() > 0) {
                wardService.updateBedOccupancy(record.getWardId(), ward.getOccupiedBeds() - 1);
            }
        }
        
        return success;
    }

    @Override
    public List<Integer> getAvailableBeds(Long wardId) {
        // 获取病房信息
        Ward ward = wardService.getById(wardId);
        if (ward == null) {
            throw new RuntimeException("病房不存在");
        }

        // 获取已占用的床位号
        QueryWrapper<MedicalRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("bed_number")
                   .eq("ward_id", wardId)
                   .eq("hospitalization_status", 1) // 已入院状态
                   .eq("deleted", 0);
        
        List<Object> occupiedBeds = listObjs(queryWrapper);
        Set<Integer> occupiedBedNumbers = occupiedBeds.stream()
                .map(obj -> Integer.parseInt(obj.toString()))
                .collect(Collectors.toSet());

        // 生成可用床位号列表
        List<Integer> availableBeds = new ArrayList<>();
        for (int i = 1; i <= ward.getTotalBeds(); i++) {
            if (!occupiedBedNumbers.contains(i)) {
                availableBeds.add(i);
            }
        }

        return availableBeds;
    }
} 